---
title: "Where do parties interact? Issue engagement in press releases and tweets"
subtitle: "Tables and Figures"
author: "Christoph Ivanusch"
date: "`r Sys.Date()`"
output: pdf_document
link-citations: yes
urlcolor: red
toc: yes
header-includes:
  - \usepackage{float}
  - \usepackage{subfig}
  - \captionsetup{belowskip=0pt,aboveskip=4pt}
  - \usepackage{setspace}
  - \usepackage{lscape}

---

```{r, setup, include=FALSE, echo=FALSE, warning=FALSE, message=FALSE}

# chunk option defaults
knitr::opts_chunk$set(echo = FALSE, message = FALSE)

# packages
library(quanteda)
library(quanteda.textstats)
library(tidyverse)
library(dplyr)
library(xlsx)
library(readxl)
library(lubridate)
library(ggplot2)
library(ggforce)
library(gridExtra)
library(formattable)
library(xtable)
library(kableExtra)
library(ggeffects)
library(manifestoR)
library(zoo)
library(miceadds)
library(stargazer)
library(estimatr)
library(lfe)
library(patchwork)
library(sampling)
library(ggraph)
library(tidygraph)
library(igraph)
library(oolong)
library(marginaleffects)

# custom function
printT <- function(x) {formatC(x, format="d", big.mark=",")}

```

```{r, echo=FALSE, warning=FALSE, message=FALSE}

# Main data set

## load main data set
main_data <- readRDS("Main_Data.RDS")

## create cluster variable
main_data$cluster <- paste0(main_data$party_dyad, "-", main_data$topic_label)

# Text corpora

corpus_pressreleases <- readRDS("Corpus_Pressreleases_AT_CH_DE.RDS")

corpus_tweets <- readRDS("Corpus_Tweets_AT_CH_DE.RDS") %>%
  filter(party != "FPÖ/VDU") %>%
  filter(party != "PILZ/JETZT")

corp <- (rbind(corpus_pressreleases[, c("text_id", "country", "party", "date", "timestamp", "type", "text")],
               corpus_tweets[, c("text_id", "country", "party", "date", "timestamp", "type", "text")]))
corp$country <- as.factor(corp$country)

# STM output

stm_res <- readRDS("../Replication Material/STM_Result.RDS")

idx_fpo <- sort(c(which(stm_res$party == "FPÖ/VDU" & stm_res$type == "Tweet")))
stm_res <- stm_res[-idx_fpo, ]

stm_res_pressrelease <- filter(stm_res, type == "Press release")
df_salience_pressrelease <- data.frame(
  (table(stm_res_pressrelease$topic_label) / nrow(stm_res_pressrelease)) * 100
  )

stm_res_tweet <- filter(stm_res, type == "Tweet")
df_salience_tweet <- data.frame(
  (table(stm_res_tweet$topic_label) / nrow(stm_res_tweet)) * 100
  )

df_salience <- left_join(df_salience_pressrelease,
                         df_salience_tweet,
                         by = "Var1")
colnames(df_salience) <- c("topic_label", 
                           "frequency_pressreleases", 
                           "frequency_tweets")

```

\newpage

# Article

## Table 1

```{r, warning=FALSE, message=FALSE, echo=FALSE, results="asis"}

# create table
df <- corp

df$n <- 1

df1 <- df %>%
  group_by(country, type) %>%
  summarise(values = sum(n)) %>%
  spread(key = "type", value = "values")

df2 <- df %>%
  group_by(type) %>%
  summarise(values = sum(n)) %>%
  spread(key = "type", value = "values")

df <- rbind(df1, df2)
df$country <- as.character(df$country)
df$country[4] <- "All"

colnames(df)[1] <- "Country"

df <- as.data.frame(df)

df$`Press release` <- printT(df$`Press release`)
df$Tweet <- printT(df$Tweet)

# print table
print(xtable(df, align = c("l", "l", "c", "c"),
      caption = "Number of press releases and tweets between January 2019 and September 2021."),
      caption.placement = "top",
      hline.after = c(-1, 0, 3, 4), comment = FALSE, include.rownames = FALSE)

```

\newpage

## Table 2

```{r, warning=FALSE, message=FALSE, echo=FALSE, results="asis"}

# data on full population of interest (i.e. all potential occurrences of issue engagement)
data_sub <- main_data %>%
  filter(attention_source > 0)

data_population1 <- data.frame(table(data_sub$type, data_sub$country)) %>%
  spread(key = "Var1", value = "Freq") %>%
  rename("country" = "Var2") %>%
  rename("All_pressrelease" = "Press release") %>%
  rename("All_tweet" = "Tweet")

data_population2 <- data.frame(
  country = "All",
  "All_pressrelease" = sum(data_population1$All_pressrelease),
  "All_tweet" = sum(data_population1$All_tweet)
)

data_population <- rbind(data_population1, data_population2)

# data on observed occurrences of issue engagement

## t-0
df1.1 <- main_data %>% 
  group_by(country, type) %>%
  summarise(values = sum(issue_engagement_tplus0, na.rm = TRUE)) %>%
  spread(key = "type", value = "values")
colnames(df1.1)[2:3] <- c("N_pressrelease", "N_tweet")

df1.2 <- data.frame(country = "All",
                    `N_pressrelease` = sum(df1.1$N_pressrelease),
                    `N_tweet` = sum(df1.1$N_tweet))
 
df1 <- rbind(df1.1, df1.2) %>%
  left_join(data_population) %>%
  mutate("pressrelease" = paste0(
    printT(N_pressrelease), "\n(", round(N_pressrelease / All_pressrelease * 100, digits = 0), "\\%)")
    ) %>%
  mutate("tweet" = paste0(
    printT(N_tweet), "\n(", round(N_tweet / All_tweet * 100, digits = 0), "\\%)")
    ) %>%
  select(country, pressrelease, tweet)

## t-1
df2.1 <- main_data %>% 
  group_by(country, type) %>%
  summarise(values = sum(issue_engagement_tplus1, na.rm = TRUE)) %>%
  spread(key = "type", value = "values")
colnames(df2.1)[2:3] <- c("N_pressrelease", "N_tweet")

df2.2 <- data.frame(country = "All",
                    `N_pressrelease` = sum(df2.1$N_pressrelease),
                    `N_tweet` = sum(df2.1$N_tweet))
 
df2 <- rbind(df2.1, df2.2) %>%
  left_join(data_population) %>%
  mutate("pressrelease" = paste0(
    printT(N_pressrelease), "\n(", round(N_pressrelease / All_pressrelease * 100, digits = 0), "\\%)")
    ) %>%
  mutate("tweet" = paste0(
    printT(N_tweet), "\n(", round(N_tweet / All_tweet * 100, digits = 0), "\\%)")
    ) %>%
  select(country, pressrelease, tweet)

## t-2
df3.1 <- main_data %>% 
  group_by(country, type) %>%
  summarise(values = sum(issue_engagement_tplus2, na.rm = TRUE)) %>%
  spread(key = "type", value = "values")
colnames(df3.1)[2:3] <- c("N_pressrelease", "N_tweet")

df3.2 <- data.frame(country = "All",
                    `N_pressrelease` = sum(df3.1$N_pressrelease),
                    `N_tweet` = sum(df3.1$N_tweet))
 
df3 <- rbind(df3.1, df3.2) %>%
  left_join(data_population) %>%
  mutate("pressrelease" = paste0(
    printT(N_pressrelease), "\n(", round(N_pressrelease / All_pressrelease * 100, digits = 0), "\\%)")
    ) %>%
  mutate("tweet" = paste0(
    printT(N_tweet), "\n(", round(N_tweet / All_tweet * 100, digits = 0), "\\%)")
    ) %>%
  select(country, pressrelease, tweet)

## t-3
df4.1 <- main_data %>% 
  group_by(country, type) %>%
  summarise(values = sum(issue_engagement_tplus3, na.rm = TRUE)) %>%
  spread(key = "type", value = "values")
colnames(df4.1)[2:3] <- c("N_pressrelease", "N_tweet")

df4.2 <- data.frame(country = "All",
                    `N_pressrelease` = sum(df4.1$N_pressrelease),
                    `N_tweet` = sum(df4.1$N_tweet))
 
df4 <- rbind(df4.1, df4.2) %>%
  left_join(data_population) %>%
  mutate("pressrelease" = paste0(
    printT(N_pressrelease), "\n(", round(N_pressrelease / All_pressrelease * 100, digits = 0), "\\%)")
    ) %>%
  mutate("tweet" = paste0(
    printT(N_tweet), "\n(", round(N_tweet / All_tweet * 100, digits = 0), "\\%)")
    ) %>%
  select(country, pressrelease, tweet)

# create table
df <- cbind(df1, df2) %>%
  cbind(df3) %>%
  cbind(df4)

df <- df[, c(1:3, 5:6, 8:9, 11:12)]

df <- as.data.frame(df)

# print table
df %>%
  mutate_all(linebreak, align = "c") %>%
  kable(format = "latex",
        booktabs = TRUE,
        escape = FALSE,
        align = c("l", "c", "c", "c", "c", "c", "c", "c", "c"),
        col.names = c("Country", 
                      "Press release", "Tweet", "Press release", "Tweet",
                      "Press release", "Tweet", "Press release", "Tweet"),
        caption = "Number of issue engagement occurrences across all party-dyads per text type and country between January 2019 and September 2021. The percentages provided in parentheses indicate the observed occurrences of issue engagement relative to the number of potential occurrences.")  %>%
  add_header_above(c(" " = 1, "One-day period" = 2, "Two-day period" = 2,
                     "Three-day period" = 2, "Four-day period" = 2)) %>%
  kable_styling(latex_options = c("scale_down", "HOLD_position")) %>%
  row_spec(3, hline_after = TRUE)

```

\newpage

## Figure 1

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.align="center", out.width="100%", fig.cap = "Top-10 issues with highest level of issue engagement (four-day period) in press releases and tweets between January 2019 and September 2021."}

# top-10 in press releases
df1 <- filter(main_data, type == "Press release") %>%
  group_by(topic_label) %>%
  summarize(N = sum(issue_engagement_tplus3, na.rm = TRUE)) %>%
  arrange(desc(N)) %>%
  mutate(type = "Press release")

# top-10 in tweets
df2 <- filter(main_data, type == "Tweet") %>%
  group_by(topic_label) %>%
  summarize(N = sum(issue_engagement_tplus3, na.rm = TRUE)) %>%
  arrange(desc(N)) %>%
  mutate(type = "Tweet")

# create table
topic_label_list <- unique(unlist(c(df1[1:10, 1], df2[1:10, 1])))

df <- rbind(
  data.frame(topic_label = topic_label_list, type = "Press release") %>%
    left_join(df1),
  data.frame(topic_label = topic_label_list, type = "Tweet") %>%
  left_join(df2))

# print table
ggplot(df, aes(y = fct_rev(topic_label), x = N, fill = type)) + 
  geom_bar(stat = "identity",  position=position_dodge()) +
  theme_bw() +
  ggtitle("") +
  scale_fill_manual(values = c("grey70", "grey10")) +
  labs(x = "N", y = "Issue", fill = "Text type")

```

\newpage

## Figure 2

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.ncol = 2, out.width = "50%", fig.align = "center", fig.cap = "Issue engagement (four-day period) network between parties in press releases and tweets between January 2019 and September 2021.", fig.subcap=c('Austria', 'Germany', 'Switzerland')}

# Austria
## create data frame
df <- filter(main_data,
             issue_engagement_tplus3 > 0 & country == "AT") %>%
  group_by(party_dyad_sorted, type) %>%
  summarise_at(c("issue_engagement_tplus3"), sum, na.rm = TRUE)

df$party_a <- str_extract(df$party_dyad_sorted,
                          "[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- str_extract(df$party_dyad_sorted,
                          "-[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- gsub("\\-", "", df$party_b)
df <- df[, c("party_a", "party_b", "type", "issue_engagement_tplus3")]

## adjust party names
df$party_a <- gsub("FPÖ/VDU", "FPÖ", df$party_a)
df$party_a <- gsub("Grüne/GA", "Greens", df$party_a)
df$party_b <- gsub("FPÖ/VDU", "FPÖ", df$party_b)
df$party_b <- gsub("Grüne/GA", "Greens", df$party_b)

## graph object
graph <- as_tbl_graph(df, directed = FALSE)
edge_weight <- df$issue_engagement_tplus3 / 10000

graph <- graph %>%
  tidygraph::activate(edges) %>%
  mutate(edge_weights = edge_weight)

## plot
set.seed(5)
ggraph(graph, layout = "fr", weights = edge_weights) +
  geom_edge_link(aes(alpha = 0.5, width = edge_weights, color = edge_weights),
                 show.legend = FALSE) +
  scale_edge_colour_gradient(low = "grey", high = "black") +
  geom_node_point() +
  scale_edge_alpha_identity() +
  geom_node_label(aes(label = name), 
                 size = 6,
                 position = position_dodge(width = 1)) +
  facet_edges(~type) +
  theme_bw() +
  theme(axis.title = element_blank(), 
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        panel.grid = element_blank(),
        strip.text.x = element_text(size = 24))

# Germany

## create data frame
df <- filter(main_data,
             issue_engagement_tplus3 > 0 & country == "DE") %>%
  group_by(party_dyad_sorted, type) %>%
  summarise_at(c("issue_engagement_tplus3"), sum, na.rm = TRUE)

df$party_a <- str_extract(df$party_dyad_sorted,
                          "[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- str_extract(df$party_dyad_sorted,
                          "-[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- gsub("\\-", "", df$party_b)
df <- df[, c("party_a", "party_b", "type", "issue_engagement_tplus3")]

## adjust party names
df$party_a <- gsub("Bündnis90/Die Grünen", "Greens", df$party_a)
df$party_a <- gsub("Linke/PDS", "Left", df$party_a)
df$party_b <- gsub("Bündnis90/Die Grünen", "Greens", df$party_b)
df$party_b <- gsub("Linke/PDS", "Left", df$party_b)

## graph object
graph <- as_tbl_graph(df, directed = FALSE)
edge_weight <- df$issue_engagement_tplus3 / 10000

graph <- graph %>%
  tidygraph::activate(edges) %>%
  mutate(edge_weights = edge_weight)

## plot
set.seed(1)
ggraph(graph, layout = "fr", weights = edge_weights) +
  geom_edge_link(aes(alpha = 0.5, width = edge_weights, color = edge_weights), 
                 show.legend = FALSE) +
  scale_edge_colour_gradient(low = "grey", high = "black") + 
  geom_node_point() +
  scale_edge_alpha_identity() +
  geom_node_label(aes(label = name), 
                 size = 6,
                 position = position_dodge(width = 1)) +
  facet_edges(~type) +
  theme_bw() +
  theme(axis.title = element_blank(), 
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        panel.grid = element_blank(),
        strip.text.x = element_text(size = 24))

# Switzerland

## create data frame
df <- filter(main_data,
             issue_engagement_tplus3 > 0 & country == "CH") %>%
  mutate(party_dyad_sorted = gsub("Mitte", "CVP/Mitte", party_dyad_sorted)) %>%
  mutate(party_dyad_sorted = gsub("CVP/PDC", "CVP/Mitte", party_dyad_sorted)) %>%
  group_by(party_dyad_sorted, type) %>%
  summarise_at(c("issue_engagement_tplus3"), sum, na.rm = TRUE)

df$party_a <- str_extract(df$party_dyad_sorted,
                          "[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- str_extract(df$party_dyad_sorted,
                          "-[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- gsub("\\-", "", df$party_b)
df <- df[, c("party_a", "party_b", "type", "issue_engagement_tplus3")]

## adjust party names
df$party_a <- gsub("BDP/PBD", "BDP", df$party_a)
df$party_a <- gsub("FDP/PLR", "FDP", df$party_a)
df$party_a <- gsub("GPS/PES", "GPS", df$party_a)
df$party_a <- gsub("SPS/PSS", "SPS", df$party_a)
df$party_a <- gsub("SVP/UDC", "SVP", df$party_a)
df$party_b <- gsub("BDP/PBD", "BDP", df$party_b)
df$party_b <- gsub("FDP/PLR", "FDP", df$party_b)
df$party_b <- gsub("GPS/PES", "GPS", df$party_b)
df$party_b <- gsub("SPS/PSS", "SPS", df$party_b)
df$party_b <- gsub("SVP/UDC", "SVP", df$party_b)

## graph object
graph <- as_tbl_graph(df, directed = FALSE)
edge_weight <- df$issue_engagement_tplus3 / 10000

graph <- graph %>%
  tidygraph::activate(edges) %>%
  mutate(edge_weights = edge_weight)

## plot
set.seed(10)
ggraph(graph, layout = "fr", weights = edge_weights) +
  geom_edge_link(aes(alpha = 0.5, width = edge_weights, color = edge_weights), 
                 show.legend = FALSE) +
  scale_edge_colour_gradient(low = "grey", high = "black") +
  geom_node_point() +
  scale_edge_alpha_identity() +
  geom_node_label(aes(label = name), 
                 size = 6,
                 position = position_dodge(width = 1)) +
  facet_edges(~type) +
  theme_bw() +
  theme(axis.title = element_blank(), 
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        panel.grid = element_blank(),
        strip.text.x = element_text(size = 24))

```

\newpage

## Table 3

```{r, warning=FALSE, message=FALSE, echo=FALSE, results='hide'}

# filter data
data_sub <- filter(main_data, attention_source > 0)
data_sub$party_government <- as.factor(data_sub$party_government)

# t+0
m1 <- miceadds::glm.cluster(
  data = data_sub,
  formula = issue_engagement_tplus0 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m1_summary <- data.frame(summary(m1))[c(1:5, 46:48, 6:7), 1:4]
colnames(m1_summary) <- c("est", "sd", "z", "p")

# t+1
m2 <- miceadds::glm.cluster(
  data = data_sub,
  formula = issue_engagement_tplus1 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m2_summary <- data.frame(summary(m2))[c(1:5, 46:48, 6:7), 1:4]
colnames(m2_summary) <- c("est", "sd", "z", "p")

# t+2
m3 <- miceadds::glm.cluster(
  data = data_sub,
  formula = issue_engagement_tplus2 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m3_summary <- data.frame(summary(m3))[c(1:5, 46:48, 6:7), 1:4]
colnames(m3_summary) <- c("est", "sd", "z", "p")

# t+3
m4 <- miceadds::glm.cluster(
  data = data_sub,
  formula = issue_engagement_tplus3 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type + 
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m4_summary <- data.frame(summary(m4))[c(1:5, 46:48, 6:7), 1:4]
colnames(m4_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus0 ~ # dependent variable
                type + 
                rile_difference*type + 
                party_perseat*type +
                party_government*type + 
                election_campaign +
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm, fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models with moderating factors for issue engagement between parties.",
          dep.var.labels = "Issue engagement",
          coef = list(m1_summary$est, m2_summary$est, 
                      m3_summary$est, m4_summary$est),
          se = list(m1_summary$sd, m2_summary$sd,
                    m3_summary$sd, m4_summary$sd),
          p = list(m1_summary$p, m2_summary$p,
                   m3_summary$p, m4_summary$p),
          covariate.labels = c("Tweet",
                               "RILE difference",
                               "Party size",
                               "Party in government",
                               "RILE difference:Tweet", 
                               "Party size:Tweet",
                               "Party in government:Tweet",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "Yes", "Yes", "Yes"),
                           c("Issue FEs", "Yes", "Yes", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m1$glm_res), digits = 1)),
                             printT(round(logLik(m2$glm_res), digits = 1)),
                             printT(round(logLik(m3$glm_res), digits = 1)),
                             printT(round(logLik(m4$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m1$glm_res$aic, digits = 1)),
                             printT(round(m2$glm_res$aic, digits = 1)),
                             printT(round(m3$glm_res$aic, digits = 1)),
                             printT(round(m4$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m1$glm_res$data)),
                             printT(nrow(m2$glm_res$data)),
                             printT(nrow(m3$glm_res$data)),
                             printT(nrow(m4$glm_res$data)))),
        notes = "Standard errors are clustered by party dyad-issue.")

```

\newpage

## Figure 3

```{r, warning=FALSE, message=FALSE, echo=FALSE, out.width = "100%", fig.align = "center", fig.cap = "Predicted probabilities for issue engagement (four-day period) in press releases and tweets. The plots on the left show marginal predictions (i.e. predictions computed on the original data, but averaged by subgroups) based on categorical variables; the plots on the right require conditional predictions (i.e. predictions computed on a substantively meaningful grid of predictor values) due to the inclusion of continuous variables."}

# print plots
grid.arrange(
plot_predictions(m4$glm_res, 
                 by = c("type"), 
                 vcov = m4$vcov,
                 gray = TRUE,
                 ) +
  labs(x = "Type", y = "Probability", group = "Type") +
  theme_bw() +
  theme(legend.position = "bottom"),
plot_predictions(m4$glm_res, 
                 condition = c("rile_difference", "type"), 
                 vcov = m4$vcov,
                 gray = TRUE,
                 ) +
  labs(x = "Rile difference", y = "Probability", linetype = "Type") +
  theme_bw() +
  theme(legend.position = "bottom"),
plot_predictions(m4$glm_res, 
                 by = c("party_government", "type"), 
                 vcov = m4$vcov,
                 gray = TRUE,
                 ) +
  labs(x = "Party in government", y = "Probability", shape = "Type") +
  scale_x_discrete(labels = c('Opposition','Government')) +
  theme_bw()+
  theme(legend.position = "bottom"),
plot_predictions(m4$glm_res, 
                 condition = c("party_perseat", "type"), 
                 vcov = m4$vcov,
                 gray = TRUE,
                 ) +
  labs(x = "Party size", y = "Probability", linetype = "Type") +
  theme_bw() +
  theme(legend.position = "bottom"),
ncol = 2
)

```

\newpage

# Appendix

## A.1 Number of press releases and tweets over time

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.align="center", out.width="100%", fig.cap = "Evolution of the number of press releases and tweets published by parties between January 2019 and September 2021."}

# print plot
ggplot(corp, aes(x=date, fill = country)) + 
  geom_histogram(aes(y=..count..),, binwidth = 7, position="identity", alpha=0.25) + 
  geom_density(aes(y=..count..*7), alpha=.5) +
  facet_wrap(~type, ncol = 2) +
  xlab("date") +
  theme_bw() +
  scale_x_date(date_labels = "%m/%Y") +
  ylim(0, 500) +
  theme(axis.text.x = element_text(angle = 90)) +
  labs(x = "Date", y = "Count", fill = "Country")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.align="center", out.width="100%", fig.cap = "Evolution of the number of press releases and tweets published by each Austrian party between January 2019 and September 2021."}

# print plot
corp %>%
  filter(country == "AT") %>%
  ggplot(aes(x=date, fill = type)) + 
  geom_histogram(aes(y=..count..),, binwidth = 7, position="identity", alpha=0.25) + 
  geom_density(aes(y=..count..*7), alpha=.5) +
  facet_wrap(~party, ncol = 2) +
  xlab("date") +
  theme_bw() +
  scale_x_date(date_labels = "%m/%Y") +
  scale_fill_grey() +
  ylim(0, 250) +
  theme(axis.text.x = element_text(angle = 90)) +
  labs(x = "Date", y = "Count", fill = "Type")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.align="center", out.width="100%", fig.cap = "Evolution of the number of press releases and tweets published by each German party between January 2019 and September 2021."}

# print plot
corp %>%
  filter(country == "DE") %>%
  ggplot(aes(x=date, fill = type)) + 
  geom_histogram(aes(y=..count..),, binwidth = 7, position="identity", alpha=0.25) + 
  geom_density(aes(y=..count..*7), alpha=.5) +
  facet_wrap(~party, ncol = 2) +
  xlab("date") +
  theme_bw() +
  scale_x_date(date_labels = "%m/%Y") +
  scale_fill_grey() +
  ylim(0, 250) +
  theme(axis.text.x = element_text(angle = 90)) +
  labs(x = "Date", y = "Count", fill = "Type")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.align="center", out.width="100%", fig.cap = "Evolution of the number of press releases and tweets published by each Swiss party between January 2019 and September 2021."}

# print plot
corp %>%
  filter(country == "CH") %>%
  ggplot(aes(x=date, fill = type)) + 
  geom_histogram(aes(y=..count..),, binwidth = 7, position="identity", alpha=0.25) + 
  geom_density(aes(y=..count..*7), alpha=.5) +
  facet_wrap(~party, ncol = 2) +
  xlab("date") +
  theme_bw() +
  scale_x_date(date_labels = "%m/%Y") +
  scale_fill_grey() +
  ylim(0, 50) +
  theme(axis.text.x = element_text(angle = 90)) +
  labs(x = "Date", y = "Count", fill = "Type")

```

\newpage

## A.2 Application of structural topic model (STM)

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.align="center", out.width="100%", fig.cap = "Development of semantic coherence, exclusivity, held-out likelihood and residuals for different numbers of topics (k) of structural topic model (STM)."}

# load model
stm_model <- load("STM_Model.RDA")

# semantic coherence
semcoh <- as.numeric(finding_k$results$semcoh)
names(semcoh) <- finding_k$results$K
df_semcoh <- data.frame(k = as.numeric(names(semcoh)), semcoh = semcoh) %>%
  arrange(k)

# exclusivity
exclus <- as.numeric(finding_k$results$exclus)
names(exclus) <- finding_k$results$K
df_exclus <- data.frame(k = as.numeric(names(exclus)), exclus = exclus) %>%
  arrange(k)

# held-out likelihood
heldout <- as.numeric(finding_k$results$heldout)
names(heldout) <- finding_k$results$K
df_heldout <- data.frame(k = as.numeric(names(heldout)), heldout = heldout) %>%
  arrange(k)

# residuals
residual <- as.numeric(finding_k$results$residual)
names(residual) <- finding_k$results$K
df_residual <- data.frame(k = as.numeric(names(residual)), residual = residual) %>%
  arrange(k)

# print plots
grid.arrange(
  
  ggplot(df_semcoh, aes(x = k, y = semcoh)) + 
    geom_point() +
    geom_line() +
    theme_bw() +
    labs(x = "Number of topics", y = "Semantic coherence"),
  
  ggplot(df_exclus, aes(x = k, y = exclus)) + 
    geom_point() +
    geom_line() +
    theme_bw() +
    labs(x = "Number of topics", y = "Exclusivity"),
  
  ggplot(df_heldout, aes(x = k, y = heldout)) + 
    geom_point() +
    geom_line() +
    theme_bw() +
    labs(x = "Number of topics", y = "Held-out likelihood"),
  
  ggplot(df_residual, aes(x = k, y = residual)) +
    geom_point() +
    geom_line() +
    theme_bw() +
    labs(x = "Number of topics", y = "Residuals"),
  
  ncol = 2
  
)
  
```

```{r tab1, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

## call validation script
source("STM_Validation.R")

# create table
df_validation <- df_summary
colnames(df_validation) <- c("Number of topics (k)", "Mean model precision", "Mean TLO")

df_validation[, 2:3] <- round(df_validation[, 2:3], digits = 2)

# print table
kable(df_validation,
      format = "latex", booktabs = TRUE,
      align = c("l", "c", "c"),
      row.names = FALSE,
      caption = "Mean model precision from word intrusion test and mean topic log odds (TLO) from topic intrusion tests for the applied structural topic models (STM).")  %>%
  kable_styling(latex_options = "HOLD_position")

```

\newpage

## A.3 Labelled STM topics

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# load topics and labels
stm_topics <- read.xlsx("STM_Topics_labeled.xlsx",
                        sheetIndex = 1)

# print table
kable(stm_topics[, 2:12],
      format = "latex", 
      booktabs = TRUE, 
      longtable = TRUE,
      row.names = TRUE,
      caption = "Top-10 words per topic provided by the Structural Topic Model with manually assigned topic labels.")  %>%
  kable_styling(latex_options = c("HOLD_position", "repeat_header"), font_size = 3) %>%
  kableExtra::landscape()

```

\newpage

## A.4 Issue salience in press releases and tweets

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# Overall salience

## number of topic occurrences per text type
df_topic_n <- stm_res %>%
  filter(topic_label != "NA") %>%
  filter(topic_label != "Event information") %>%
  filter(topic_label != "Thanks and wishes") %>%
  filter(topic_label != "Legislation and initiatives") %>%
  filter(!is.na(topic_label)) %>%
  group_by(type, topic_label) %>%
  count(topic_label)
colnames(df_topic_n)[3] <- "n_topic"

## number of documents per text type
df_type_n <- stm_res %>%
  filter(topic_label != "NA") %>%
  filter(topic_label != "Event information") %>%
  filter(topic_label != "Thanks and wishes") %>%
  filter(topic_label != "Legislation and initiatives") %>%
  filter(!is.na(topic_label)) %>%
  count(type)
colnames(df_type_n)[2] <- "n_type"

## issue salience in percent
df_topic_salience_all <- left_join(df_topic_n, df_type_n)
df_topic_salience_all$salience <- (df_topic_salience_all$n_topic / 
                                 df_topic_salience_all$n_type) * 100
df_topic_salience_all <- df_topic_salience_all[, c(1:2, 5)] %>%
  spread(type, salience)
df_topic_salience_all$`Press release`[which(is.na(df_topic_salience_all$`Press release`))] <- 0
df_topic_salience_all$`Tweet`[which(is.na(df_topic_salience_all$`Tweet`))] <- 0

colnames(df_topic_salience_all) <- c("topic_label", "pr_all", "tw_all")

# Austria

## number of topic occurrences per text type
df_topic_n <- stm_res %>%
  filter(country == "AT") %>%
  filter(topic_label != "NA") %>%
  filter(topic_label != "Event information") %>%
  filter(topic_label != "Thanks and wishes") %>%
  filter(topic_label != "Legislation and initiatives") %>%
  filter(!is.na(topic_label)) %>%
  group_by(type, topic_label) %>%
  count(topic_label)
colnames(df_topic_n)[3] <- "n_topic"

## number of documents per text type
df_type_n <- stm_res %>%
  filter(country == "AT") %>%
  filter(topic_label != "NA") %>%
  filter(topic_label != "Event information") %>%
  filter(topic_label != "Thanks and wishes") %>%
  filter(topic_label != "Legislation and initiatives") %>%
  filter(!is.na(topic_label)) %>%
  count(type)
colnames(df_type_n)[2] <- "n_type"

## issue salience in percent
df_topic_salience_at <- left_join(df_topic_n, df_type_n)
df_topic_salience_at$salience <- (df_topic_salience_at$n_topic / 
                                 df_topic_salience_at$n_type) * 100
df_topic_salience_at <- df_topic_salience_at[, c(1:2, 5)] %>%
  spread(type, salience)
df_topic_salience_at$`Press release`[which(is.na(df_topic_salience_at$`Press release`))] <- 0
df_topic_salience_at$`Tweet`[which(is.na(df_topic_salience_at$`Tweet`))] <- 0

colnames(df_topic_salience_at) <- c("topic_label", "pr_at", "tw_at")

# Switzerland

## number of topic occurrences per text type
df_topic_n <- stm_res %>%
  filter(country == "CH") %>%
  filter(topic_label != "NA") %>%
  filter(topic_label != "Event information") %>%
  filter(topic_label != "Thanks and wishes") %>%
  filter(topic_label != "Legislation and initiatives") %>%
  filter(!is.na(topic_label)) %>%
  group_by(type, topic_label) %>%
  count(topic_label)
colnames(df_topic_n)[3] <- "n_topic"

## number of documents per text type
df_type_n <- stm_res %>%
  filter(country == "CH") %>%
  filter(topic_label != "NA") %>%
  filter(topic_label != "Event information") %>%
  filter(topic_label != "Thanks and wishes") %>%
  filter(topic_label != "Legislation and initiatives") %>%
  filter(!is.na(topic_label)) %>%
  count(type)
colnames(df_type_n)[2] <- "n_type"

## issue salience in percent
df_topic_salience_ch <- left_join(df_topic_n, df_type_n)
df_topic_salience_ch$salience <- (df_topic_salience_ch$n_topic / 
                                 df_topic_salience_ch$n_type) * 100
df_topic_salience_ch <- df_topic_salience_ch[, c(1:2, 5)] %>%
  spread(type, salience)
df_topic_salience_ch$`Press release`[which(is.na(df_topic_salience_ch$`Press release`))] <- 0
df_topic_salience_ch$`Tweet`[which(is.na(df_topic_salience_ch$`Tweet`))] <- 0

colnames(df_topic_salience_ch) <- c("topic_label", "pr_ch", "tw_ch")

# Germany

## number of topic occurrences per text type
df_topic_n <- stm_res %>%
  filter(country == "DE") %>%
  filter(topic_label != "NA") %>%
  filter(topic_label != "Event information") %>%
  filter(topic_label != "Thanks and wishes") %>%
  filter(topic_label != "Legislation and initiatives") %>%
  filter(!is.na(topic_label)) %>%
  group_by(type, topic_label) %>%
  count(topic_label)
colnames(df_topic_n)[3] <- "n_topic"

## number of documents per text type
df_type_n <- stm_res %>%
  filter(country == "DE") %>%
  filter(topic_label != "NA") %>%
  filter(topic_label != "Event information") %>%
  filter(topic_label != "Thanks and wishes") %>%
  filter(topic_label != "Legislation and initiatives") %>%
  filter(!is.na(topic_label)) %>%
  count(type)
colnames(df_type_n)[2] <- "n_type"

## issue salience in percent
df_topic_salience_de <- left_join(df_topic_n, df_type_n)
df_topic_salience_de$salience <- (df_topic_salience_de$n_topic / 
                                 df_topic_salience_de$n_type) * 100
df_topic_salience_de <- df_topic_salience_de[, c(1:2, 5)] %>%
  spread(type, salience)
df_topic_salience_de$`Press release`[which(is.na(df_topic_salience_de$`Press release`))] <- 0
df_topic_salience_de$`Tweet`[which(is.na(df_topic_salience_de$`Tweet`))] <- 0

colnames(df_topic_salience_de) <- c("topic_label", "pr_de", "tw_de")

# create full table

df_topic_salience <- left_join(df_topic_salience_all, df_topic_salience_at) %>% 
  left_join(df_topic_salience_ch) %>%
  left_join(df_topic_salience_de)

df_topic_salience$pr_ch[which(is.na(df_topic_salience$pr_ch) == TRUE)] <- 0
df_topic_salience$tw_ch[which(is.na(df_topic_salience$tw_ch) == TRUE)] <- 0

df_topic_salience[, 2:9] <- round(df_topic_salience[, 2:9], digits = 2)
colnames(df_topic_salience) <- c("Topic label", 
                                 "Press releases", "Tweets", "Press releases", "Tweets",
                                 "Press releases", "Tweets", "Press releases", "Tweets")

# print table
kable(df_topic_salience,
      format = "latex", booktabs = TRUE,
      align = c("l", "c", "c", "c", "c", "c", "c", "c", "c"),
      caption = "Comparison of issue salience (in percent) in press releases and tweets between January 2019 and September 2021.") %>% 
  add_header_above(c(" " = 1, "All" = 2, "Austria" = 2, "Switzerland" = 2, "Germany" = 2)) %>%
  kable_styling(latex_options = c("HOLD_position", "scale_down"))

```

\newpage

## A.5 Examples for issue engagement in press releases and tweets

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# print table
data.frame(country = c("AT", "AT", "AT", "AT",
                            "CH", "CH", "CH", "CH",
                            "DE", "DE", "DE", "DE"), 
                type = c("Press release", "Press release", "Tweet", "Tweet",
                         "Press release", "Press release", "Tweet", "Tweet",
                         "Press release", "Press release", "Tweet", "Tweet"),
                source = c("ÖVP", "SPÖ", "Greens", "SPÖ",
                           "BDP", "SPS", "GLP", "SVP",
                           "AfD", "CDU/CSU", "Greens", "FDP"),
                source_text = c("Haubner: Tax reform provides relief and reduces bureaucracy for our companies ÖVP business spokesman: 'Entlastung Österreich' is a guarantee for a strong and competitive business location - 'The tax reform provides relief and reduces bureaucracy in the interests of our companies. With 'Entlastung Österreich', the federal government and Finance Minister Hartwig Löger are creating the best conditions for a strong and competitive business location,' Peter Haubner, spokesperson for the economy of the New People's Party, stated today. Important measures have been taken, such as reducing bureaucracy for small businesses - for example by increasing the small business threshold for VAT from 30,000 to 35,000 euros -, simplifying tax law for payroll accounting and reducing corporation tax. The reduction in corporation tax alone would relieve domestic companies to the tune of 800 million euros per year from 2022 and 1.8 billion euros per year from 2023. Haubner: 'The federal government is creating attractive framework conditions for the location and for securing and expanding jobs.' In addition, the counter-financing of the tax reform is ensured through spending discipline, strict budget implementation and additional savings in administration and subsidies - 'and thus also the administrative surplus of the federal government for the years 2020 to 2022'. ''Relief Austria' shows how location-orientated fiscal policy works in the 21st century. With this tax reform, a relief package has been developed that will benefit employees and employers and thus our entire country,' Peter Haubner clarifies and concludes: 'We are setting a course for a successful future for Austria instead of marching in the same rut forever like others.'", 
                                "Social policy - Muchitsch criticises the government's social cuts and warns of division 'Anyone who jeopardises social peace in the country must expect resistance' - SPÖ social spokesperson Josef Muchitsch today settled accounts with the social policy of the blue-black government and the planned measures for 2019 at a press conference. Muchitsch spoke of a 'social cutback project' with regard to the 12-hour working day, the dismantling of health insurance funds, the abolition of job programmes, etc.; the FPÖ remains 'the stirrup holder for Chancellor Kurz's policies'. For Muchitsch, it is 'outrageous' how the government deals with critics, how it tries to 'expose' those who have different positions. **** 'Anyone who jeopardises social peace in the country must expect resistance, not only from the opposition or interest groups, but also from the population.' Muchitsch appealed to Kurz and Strache 'not to divide the country'. In its first year, the government had 'done everything in its power to dismantle the welfare state and destroy a well-functioning healthcare system - for the benefit of Kurz's campaign donors, large corporations and top earners'. The SPÖ social spokesperson spoke of a 'long list of sins' of the government: starting with the rushing through of the Working Hours Act, in which many promises - such as a 4-day week or the right to time off - were not kept. The so-called social security reform only served to give employers a majority in the committees - according to the Court of Auditors and experts, the promised 'patient billion' was not even possible. There are also 'hidden fouls' such as the 'business class' for the wealthy in outpatient clinics or the 48 additional management functions in social insurance, which will cost millions of euros more. Muchitsch also massively criticised the reform of the minimum income, which is still under review until 10 January. 'The fact is that the cash benefit for a married couple with one child will be less than Hartz 4 in Germany,' emphasised Muchitsch. The government had argued 'with the foreigner cudgel', in reality Austrian families with children and people with disabilities were also being penalised. Those on low incomes are also the losers when it comes to the family bonus: 'The less you earn, the less you get. If you've been unemployed for a long time, you get nothing at all. It is unique in Austria that children are differentiated and not every child is worth the same.' Muchitsch also referred to the demands of top ÖVP politicians to raise the statutory retirement age to 67 - while at the same time measures to keep older people in the labour market have been cut and partial retirement has been pushed back. The government is also doing nothing to combat the persistent basic unemployment - on the contrary, AMS funds have been cut. Muchitsch contrasted this policy with the demands of the SPÖ, including a solution to the issue of care with a state care guarantee, flexible working hours in the interests of employees and employers, retention of emergency unemployment assistance, a uniform minimum security model across the country, a labour market package for women, a significant increase in pensions, the abolition of VAT on rents and real relief for employees through tax reform. It looks like there is little left for employees in this tax reform; instead of the originally promised 14 billion euros, only 5 billion euros remain, of which 1.5 billion will be deducted for the family bonus and a further 1.7 billion euros will be claimed by industry as tax relief. 'This leaves only 1.8 billion euros for 3.7 million employees,' says Muchitsch. In comparison: in 2016, under the SPÖ chancellorship, there was still a relief of 5 billion euros only for employees. The SPÖ will therefore take a close look at what the government does to relieve the burden on employees in the tax reform. And of course the SPÖ and the party leader are in favour of wealth taxation, Muchitsch emphasised.",
                                "Especially in this difficult year, it is important to come out of the crisis by investing in the future. Our important climate policy priorities in the areas of the environment, energy and public transport have been firmly underpinned with large sums of money in the new budget.",
                                "The chaos at the BVT must finally be brought to an end. We demand a reporting obligation for the Minister of the Interior, access to files by minority resolution and an annual intelligence service report to the National Council.",
                                "Arms exports: the rejection of the BDP motion is a missed opportunity The decision of the Council of States to reject the BDP motion 'Broadening the democratic basis for arms exports' is regrettable and shows that the Council of States has not recognised the signs of the times. The framework conditions for war material exports need broad democratic support. The BDP motion demanded that responsibility for this should in future lie with Parliament, i.e. the elected representatives of the people. By rejecting the motion, the Council of States has shown that it does not take the needs of society seriously. More than 120,000 people have signed the corrective initiative so far. The population has made it clear that it does not want any easing of restrictions on the export of war material. In recent months, the initiators of the corrective initiative have held out the prospect of withdrawing the initiative if parliament incorporates the most important points of the initiative into law. The corrective initiative will now definitely be put to the vote. The rejection of the BDP motion is therefore a missed opportunity.",
                                "Judges must be independent The independence of the judiciary is enshrined in the Federal Constitution. The associated division between the various powers of the state is a central pillar of our federal state. The SP parliamentary group firmly believes that judges at the Federal Supreme Court must not receive instructions from their parties. It is therefore calling for the general elections to the Federal Supreme Court to be postponed until the winter session. Until then, the Judicial Commission must examine the independence of the candidates. 'It is unacceptable for Switzerland's largest party to exert pressure on its federal judges,' says Daniel Jositsch, SP member of the Council of States and SP parliamentary group vice-president. 'It is the task of Parliament to ensure that the people we elect or re-elect to the Federal Supreme Court for the next six years are truly independent. This scrutiny is the responsibility of the Judiciary Committee. Only it is in a position to provide guarantees that enable us to elect judges with full confidence.' The independence of the judiciary guarantees every person that their case will be dealt with according to the applicable law and not according to political preferences. 'It is not least the political parties that are subject to the law and not the other way round,' says SP National Councillor and SP parliamentary group president Roger Nordmann. 'We will therefore do everything we can tomorrow, Wednesday, to ensure that the United Federal Assembly grants the request to postpone the election.' 22 Sep 2020JusticeFederal Supreme Court",
                                "Digitalisation opens up new dimensions in the use of energy, particularly in terms of energy efficiency and decentralised energy production. Buildings should be supplied with as much self-generated energy as possible. #It's time to vote Green Liberal! #ElectionCH19",
                                "In view of the #women's strike on 14 June, the women of the SVP parliamentary group are calling for zero tolerance of violence against women. As the statistics clearly show, this has a name: non-integrated men.",
                                "Maier: Inappropriate measures in immigration and asylum policy are not supported by the AfD parliamentary group Berlin, 6 June 2019: The agenda of Wednesday's meeting of the Committee on Legal Affairs and Consumer Protection of the German Bundestag included several legislative proposals of the Federal Government on the subject of 'immigration and asylum law'; this package included the Skilled Immigration Act, a law on tolerated stay in education and employment and - once again - a law on better enforcement of the obligation to leave the country for foreigners without a residence permit. AfD Member of Parliament Jens Meier summarised his impressions of the committee meeting as follows: 'Things got heated at times in the Legal Affairs Committee. The Green and Left Party MPs in particular lamented how - allegedly - inhumane and dehumanising the federal government's legislative proposals were - without, of course, being able or perhaps wanting to present any convincing concepts of their own on how to deal with foreigners who are obliged to leave the country. Instead, one of the legislative proposals was labelled a 'human dignity abolition law' and the coalition parties were accused in all seriousness of allowing small children to starve to death according to the legislative concept - what outrageous nonsense! The SPD representative even felt compelled to accuse the Greens' presentation on unreasonable deportation detention conditions of being the 'height of mendacity' - in view of the expansion of detention places for those obliged to leave the country by the state government of Schleswig-Holstein, where the Greens are also in government. The government's legislative plans are merely an - albeit ineffectual - attempt to iron out the mistakes made in asylum policy since 2015 as best they can. In reality, the measures that have now been introduced either go in the wrong direction, as in the case of toleration for job holders, or they do not go far enough, as in the case of enforcing the obligation to leave the country. It will not be possible to solve the problems in this way. The uselessness of the plans will soon become apparent - and that is why the AfD rejected the legislative proposals in the committee, even if at least the ideas of the Greens and the Left could be blocked.'",
                                "Basic pension launched Coalition strengthens statutory pension Today, Wednesday, the Federal Cabinet adopted the draft bill for a basic pension. The CDU/CSU parliamentary group's spokesperson on labour market and social policy, Peter Weiß, commented: 'After similar plans failed in previous election periods, the coalition has shown with the draft bill on the basic pension that it stands by its agreements and strengthens the statutory pension. Anyone who has worked for at least 33 years and paid into the pension fund, raised children or cared for relatives will be better off with the basic pension than people who have not done so. The coalition is thus making it clear that it is worth paying into the pension fund. The basic pension will support people in the East and West who have worked in the low-wage sector and would otherwise be at risk of poverty in old age despite great efforts. The majority of beneficiaries will be women, as women's average wages were often lower than men's, especially in the past. In addition, women still bear the main burden of child-rearing and caring today. People in eastern Germany who were affected by the huge upheavals in the years after reunification and had to work for low wages will also benefit from the basic pension. Through the income test, we ensure that only people who need a basic pension receive it. The CDU/CSU has achieved an important goal here. Anyone who is still dependent on assistance from the basic pension despite the basic pension will in future benefit from an allowance in the basic pension if they have spent at least 33 years in one of the statutory pension schemes. The periods in the different systems will be added together. In addition, people who have been insured in one of the statutory pension schemes for at least 33 years will receive an allowance for housing benefit. The legislative process is now beginning. The Union's aim is to ensure that the basic pension not only reaches people, but is also soundly financed. The administrative burden for both beneficiaries and the administration must be kept as low as possible. We will consult intensively again during the legislative process and also listen to the experts' opinions. The fact that the basic pension is now on its way is good news for the people in our country.'",
                                "If you want to give a clear answer to Chinese state capitalism & the US digital superpower, you have to rely on innovations 'made in Europe' & on the European Union. The European Investment Bank is an important institution for this. @TheDanyal",
                                "Tadaa: It took exactly one week after #data theft for @cducsubt to call for more surveillance powers on the internet...#data retention & #internetpolice are diversionary manoeuvres. It would be more important to spin off BSI from @BMI_Bund! @KonstantinKuhle"),
           party = c("NEOS", "FPÖ", "NEOS", "Greens",
                     "GPS", "GLP", "FDP", "CVP",
                     "CDU/CSU", "Left", "SPD", "CDU/CSU"), 
           party_text = c("NEOS on tax reform: Austria fails to strengthen its position as a business location Sepp Schellhorn: 'With this shambles of a tax reform, the government is cementing Austria's reputation as a country that is hostile to entrepreneurs.'  - 'Whereas the aim used to be to be able to calculate the tax on a beer mat, this reform already requires a beer mat the size of a football pitch,' states NEOS economic spokesman Sepp Schellhorn in view of the opaque and complex tax reform, which shows no serious endeavours on the part of the government to make Austria more attractive as a business location. 'This tax system for highly qualified skilled workers and specialists, which is hostile to performance, will unfortunately remain so. The government has failed to provide any answers here. The law must finally be amended to remove the numerous exemptions, the tax base broadened and the top tax rate significantly reduced in return. The same applies to corporate taxation,' says Schellhorn. In addition, payroll accounting would become even more complicated and would finally become a 'black box' for small businesses, according to Schellhorn. 'In addition to the complicated employer/employee system, coupled with the different tax treatment of salaries and other tax exemptions, there is now also a progression in social security contributions. This law is slowly becoming a collection of exemptions, which in future will only be understood by qualified tax advisors. The payroll software manufacturers can already rejoice. We are finally calling for a reduction in non-wage labour costs. This would help many companies to finally break even. Those companies that are in international competition and therefore have to turn over every euro three times would also benefit from the reduction in non-wage labour costs,' says the NEOS economic spokesperson. The abolition of 'cold progression', which has already been postponed until the day after tomorrow, is also urgently needed to protect real wages. 'In addition, the automatic progression mechanism would spare us further unnecessary tax reform discussions that only serve to defuse the 'cold progression' 'manually',' states Schellhorn.",
                          "FPÖ-Belakowitsch: 'SPÖ-Muchitsch's criticism of the government is probably a look into the past of his ailing SPÖ' 'The SPÖ is becoming increasingly bizarre in its behaviour both internally and externally' - 'With his press conference today, SPÖ-Muchitsch is trying to distract attention from the internal quarrels of his party, which is on the ground. He is once again trying to play the Austrian population off against each other with class warfare and scary stories pulled out of thin air. However, repeating all this over and over again does not make it any truer, the only thing that remains is a look back at his own failures during the years of sinecure policies and the political standstill of his SPÖ to the detriment of Austria', reacted Freedom Party social spokesperson Dr Dagmar Belakowitsch to the press conference of trade union boss Josef Muchitsch today. 'Out of bitterness that the trade union shadow government is no longer calling the tune, the SPÖ social spokesperson seems to have consulted the crystal ball, because the minimum security reform will neither bring a deterioration for families and people with disabilities - the opposite is the case, for example through the disability supplement - nor will it lead to family poverty,' Belakowitsch continued: 'While the SPÖ decided at the time on absolute asset access, the coalition is now trying to limit this to a minimum; this means that used housing will remain untouched for three years in any case- a clear improvement.' 'But yes, Mr Muchitsch, immigrants and those entitled to asylum who refuse to integrate and reject our way of life and values will have to tighten their belts in future - and that's fair. The fact that there is no longer a standardised minimum security model in Austria is due to the negotiating failure of former SPÖ Minister Stöger and no one else. So this soap-bubble criticism, like every other criticism of the SPÖ, is just a distorted reflection of the party's own history - a history of decline and failure. What remains is an ailing, divided SPÖ, whose leader is currently being lifted onto a launching pad. This party clearly lacks a coalition partner with whom it can argue in the old fashioned way,' Belakowitsch stated. 'The criticism of the flexibilisation of working hours shows how far the SPÖ has distanced itself from the people. This new regulation is welcomed by the overwhelming majority of employees; only a small, privileged group of trade unionists called for a large demonstration in June, which will go down in history as a small rally by a few functionaries,' said Belakowitsch. 'The SPÖ has spread falsehoods about the health insurance reform so often, yet this reform is still very popular with the population. The reduction of the many functionaries hurts the SPÖ with its armchair politicians - but a structural reform that brings our social insurance into the 21st century was long overdue,' emphasised the Freedom Party social spokesperson and said that for the first time in many years, the federal government was finally doing something in Austria in favour of its own citizens. Muchitsch, the head of the trade union, should realise that opposition politics does not consist of the construction of intellectual bubbles, but of deliberate, constructive work. He should probably also think about what had caused the failure of his SPÖ, which was lying on the ground.",
                          "'This budget is not a turnaround, it merely puts a bigger plaster on the wound that the ÖVP has been inflicting on our environment for years. Because the ÖVP can continue to subsidise environmental pollution with 4.7 billion euros.' @michi_bernhard #OeNR",
                          "The #BVT becomes the 'Directorate for State Security & Intelligence Service' We are implementing a comprehensive reform. The most important points:",
                          "Arms exports: unacceptable decision by the Council of States We Greens want strict rules for arms exports that are enshrined in law. Otherwise, the Federal Council can continue to undermine the regulations. Arms exports are more important to the Council of States than neutrality and peace policy - now the electorate has the final say. The Council of States today rejected the idea of enshrining the authorisation criteria for arms exports in legislation in future (Motion 18.3394). Although this would allow Parliament to more clearly define and restrict the framework conditions for arms exports. And although only this would give voters the opportunity to use a referendum to combat any erosion. We Greens want strict rules for arms exports that are enshrined in law. Otherwise, the Federal Council can continue to undermine the regulations. Arms exports are more important to the Council of States than neutrality and peace policy - now the electorate has the final say. The Council of States' decision is absolutely unacceptable. Recent developments have clearly shown this: The War Material Ordinance is too vague and is often simply circumvented. Delivering weapons to Saudi Arabia or other countries involved in the devastating war in Yemen is an absolute no-go for us Greens. Now the electorate can use the corrective initiative to ensure that such exports are prevented in future with clear legislation. We Greens want strict rules for arms exports that are enshrined in law. Otherwise, the Federal Council can continue to undermine the regulations. Arms exports are more important to the Council of States than neutrality and peace policy - now the electorate has the final say.",
                          "The SVP and SP are negligently playing with the separation of powers When parties recommend that judges be voted out of office based on their judgements, this is diametrically opposed to the separation of powers. The Green Liberals therefore find the behaviour of the SVP parliamentary group unacceptable. However, the SP's retort of postponing the elections or not re-electing all SVP federal judges is an ill-conceived hip shot. All these party tactical skirmishes damage the institution of the Federal Supreme Court and are unworthy of Parliament. At its meeting today, the Green Liberal parliamentary group clearly backed the election proposals of the Judiciary Committee. It will elect all the proposed federal judges and reject a postponement of the election. 'Postponing the elections would be a vote of no confidence by the Federal Assembly in the Federal Supreme Court. However, we do not have a fundamental problem with the independence of the judges, but with the acceptance of the separation of powers by individual parties,' states parliamentary group president Tiana Moser.",
                          "We want to seize the #opportunities of #digitalisation and be open to #progress. To ensure that this does not remain #new territory for people in Switzerland, we are organising various campaigns to highlight our demands in the field of education:",
                          "The #CVP demands: Equal pay for equal work; Equal pensions for women and men; Recognition for family carers; Affordable and reliable childcare; Two weeks of paternity leave\n#TeamOrange #Womenstrike19",
                          "Promoting the immigration of skilled workers, limiting illegal migration Bundestag adopts comprehensive legislation on asylum and migration Today, Friday, the German Bundestag is adopting a total of seven individual laws to facilitate the immigration of skilled workers and limit illegal migration. Thorsten Frei, Deputy Chairman of the CDU/CSU parliamentary group in the German Bundestag for Home Affairs and Legal Affairs, and Hermann Gröhe, Deputy Chairman of the CDU/CSU parliamentary group in the German Bundestag for Labour and Social Affairs, commented: 'With the Skilled Immigration Act, Germany is creating a new framework for the immigration of urgently needed skilled workers. For the first time, the German labour market will be comprehensively opened to skilled workers with vocational training. However, a job and qualifications in line with German standards remain crucial prerequisites. There will be no immigration into the social security systems with the CDU and CSU. When drafting the new immigration law, we have ensured a clear distinction between asylum and labour migration. For us, convincing migration legislation not only includes promoting the immigration of skilled labour, but also the clear limitation of illegal migration. This is why we are tightening up the instruments for enforcing the departure of rejected asylum seekers by means of detention pending deportation. We are increasing the pressure on identity fraudsters and those who refuse to cooperate and are cutting benefits for migrants who have already applied for asylum in another EU country or have been recognised there as being in need of protection. Hermann Gröhe: 'The Skilled Labour Immigration Act strengthens Germany as a business location and thus prosperity and social security in our country. Even today, a shortage of skilled labour is the number one obstacle to growth in many regions. The fact that in future not only academics but also professionally qualified skilled workers from countries outside the EU will have access to the labour market in Germany is a real breakthrough. The fact that they must not only have the relevant qualifications and a job, but also German language skills, shows that we have learnt from the mistakes of the past. After all, good German language skills are an essential prerequisite for success on the labour market. It is now crucial that the economy in our country utilises the new opportunities offered by the immigration of skilled workers. It is the task of politicians to support the recruitment of urgently needed skilled labour. This includes efforts to speed up the examination and recognition of foreign professional qualifications, better counselling for interested skilled workers and especially for small and medium-sized companies, as well as more opportunities to learn German abroad. Our common goal must be to strengthen Germany in the international competition for good people.'",
                          "CDU/CSU downgrades the so-called 'basic pension' to 'basic security plus' 'The Grand Coalition's most important social policy project has become a bureaucratic and blunt sword in the fight against poverty pensions that does not even deserve its name,' explains Matthias W. Birkwald, pensions policy spokesperson for the Left Party parliamentary group, on the adoption of the so-called 'basic pension'. Mr Birkwald continued: 'The CDU/CSU alone is responsible for the cuts and the year-long delay. There is hardly anything left of the goal of protecting people who have toiled for decades on miserable wages from having to go to the welfare office, at least in old age. Instead of a so-called 'basic pension', we now have 'basic security plus' on the table. This pension supplement will not benefit three million people in future - as announced in May 2019 - but only 1.3 million. Although almost 20 per cent of all pensioner households are considered poor, only five per cent will benefit from the so-called 'basic pension'. All beneficiaries with more than 33 years in the low-wage sector will have to undergo an annual income and assets test by the tax office. Any supplement, however small, will then be reduced by a further 12.5 per cent. From a gross supplement of 300 euros, only 233 euros net will remain. This income and assets test and the 12.5 per cent reduction in the supplement must therefore be abolished, otherwise DIE LINKE will not vote in favour of this law in the Bundestag. Anyone who wants to combat poverty in old age despite many years of employment must immediately raise the statutory minimum wage to twelve euros, raise the pension level back to 53 per cent to ensure a standard of living and advocate a genuine solidarity-based minimum pension that ensures that no one has to live on less than the current 1050 euros net per month in old age. Only then would an income and asset test be justified. A poverty-proof pension must now become the benchmark set by trade unions and social organisations for the Pensions Commission.'",
                          "'The Aachen Treaty is our answer to you: to nationalists and populists in the European Union,' said @MiRo_SPD in the direction of #AfD. Anyone who sees France not as our closest friend but as a potential adversary is destroying the basis of a peaceful Europe.",
                          "'Data theft must be punished more severely', demands @rbrinkhaus in the @rponline. He sees the illegal publication\\private data of politicians and celebrities as a threat to democracy. More here"),
           topic_label = c("Economy and finances", "Labour and welfare", 
                           "Environment", "Police and security",
                           "Foreign affairs (war)", "Judiciary",
                           "Digitalisation and innovation", "Discrimination", 
                           "Migration", "Pensions", 
                           "European Union", "Internet, hate and data protection")) %>%
  kable(format = "latex", 
        booktabs = FALSE,
        longtable = TRUE,
        caption = "Examples for issue engagement between parties in press releases and tweets.",
        col.names = c("Country", "Type", "Source", "Text (source)", 
                      "Party", "Text (party)", "Issue"),
        format.args = list(big.mark = ",")) %>%
  column_spec(c(1, 3, 5), width = "1cm") %>%
  column_spec(c(4, 6), width = "7cm") %>%
  column_spec(c(7), width = "1.5cm") %>%
  kable_styling(latex_options = c("HOLD_position", "repeat_header"),
                font_size = 5) %>%
  kableExtra::landscape()

```

\newpage

## A.6 Structure of main data set

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# create table
set.seed(100)

df1 <- main_data %>%
  filter(!is.na(issue_engagement_tplus3)) %>%
  filter(attention_source <= 1) %>%
  filter(issue_engagement_tplus3 == 0) %>%
  group_by(issue_engagement_tplus3) %>%
  sample_n(size = 10) %>%
  arrange(date)

df2 <- main_data %>%
  filter(!is.na(issue_engagement_tplus3)) %>%
  filter(attention_source == 1) %>%
  group_by(issue_engagement_tplus3) %>%
  sample_n(size = 15) %>%
  arrange(date)

df <- rbind(df1, df2) %>%
  arrange(date)

# print table
kable(df[, c(1:5, 12:13, 20:23, 32:35)],
      format = "latex", booktabs = TRUE,
      caption = "Overview of structure of main data set (sample).") %>%
  kable_styling(latex_options = "scale_down") %>%
  kableExtra::landscape()

```

\newpage

## A.7 Directed issue engagement network graphs

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.align="center", out.width="100%", fig.cap = "Directed issue engagement network graph for Austrian parties in press releases and tweets (four-day period) between January 2019 and September 2021."}

## create data frame
df <- filter(main_data,
             issue_engagement_tplus3 > 0 & country == "AT") %>%
  group_by(party_dyad, type) %>%
  summarise_at(c("issue_engagement_tplus3"), sum, na.rm = TRUE)

df$party_a <- str_extract(df$party_dyad,
                          "[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- str_extract(df$party_dyad,
                          "-[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- gsub("\\-", "", df$party_b)
df <- df[, c("party_a", "party_b", "type", "issue_engagement_tplus3")]

## adjust party names
df$party_a <- gsub("FPÖ/VDU", "FPÖ", df$party_a)
df$party_a <- gsub("Grüne/GA", "Greens", df$party_a)
df$party_b <- gsub("FPÖ/VDU", "FPÖ", df$party_b)
df$party_b <- gsub("Grüne/GA", "Greens", df$party_b)

## graph object
graph <- as_tbl_graph(df, directed = TRUE)
edge_weight <- df$issue_engagement_tplus3 / 10000

graph <- graph %>%
  tidygraph::activate(edges) %>%
  mutate(edge_weights = edge_weight)

## plot
set.seed(4)
ggraph(graph, layout = "fr", weights = edge_weights) +
  geom_edge_arc(aes(alpha = 1,
                    width = edge_weight, 
                    color = edge_weights
                    ),
                strength = 0.5,
                arrow = arrow(angle = 30, length = unit(0.25, "inches"),
                              ends = "last", type = "closed"),
                check_overlap = TRUE,
                start_cap = circle(2.5, 'mm'),
                end_cap = circle(2.5, 'mm'),
                show.legend = FALSE) +
  scale_edge_width(range = c(1,1)) +
  scale_edge_colour_gradient(low = "grey", high = "black") +
  geom_node_point(size = 5, aes(color = as.factor(name))) +
  scale_color_manual(name = "Party name",
                     values = c("FPÖ" = 'blue','Greens' = 'darkgreen', "NEOS" = "pink",
                                "PILZ/JETZT" = "grey", "SPÖ" = "red", "ÖVP" = "black")) +
  scale_edge_alpha_identity() +
  facet_edges(~type) +
  theme_bw() +
  theme(axis.title = element_blank(), 
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        legend.position = "bottom",
        panel.grid = element_blank())

```

\newpage

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.align="center", out.width="100%", fig.cap = "Directed issue engagement network graph for German parties in press releases and tweets (four-day period) between January 2019 and September 2021."}

## create data frame
df <- filter(main_data,
             issue_engagement_tplus3 > 0 & country == "DE") %>%
  group_by(party_dyad, type) %>%
  summarise_at(c("issue_engagement_tplus3"), sum, na.rm = TRUE)

df$party_a <- str_extract(df$party_dyad,
                          "[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- str_extract(df$party_dyad,
                          "-[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- gsub("\\-", "", df$party_b)
df <- df[, c("party_a", "party_b", "type", "issue_engagement_tplus3")]

## adjust party names
df$party_a <- gsub("Bündnis90/Die Grünen", "Greens", df$party_a)
df$party_a <- gsub("Linke/PDS", "Left", df$party_a)
df$party_b <- gsub("Bündnis90/Die Grünen", "Greens", df$party_b)
df$party_b <- gsub("Linke/PDS", "Left", df$party_b)

## graph object
graph <- as_tbl_graph(df, directed = TRUE)
edge_weight <- df$issue_engagement_tplus3 / 10000

graph <- graph %>%
  tidygraph::activate(edges) %>%
  mutate(edge_weights = edge_weight)

## plot
set.seed(1)
ggraph(graph, layout = "fr", weights = edge_weights) +
  geom_edge_arc(aes(alpha = 1,
                    width = edge_weight, 
                    color = edge_weights
                    ),
                strength = 0.5,
                arrow = arrow(angle = 30, length = unit(0.25, "inches"),
                              ends = "last", type = "closed"),
                check_overlap = TRUE,
                start_cap = circle(2.5, 'mm'),
                end_cap = circle(2.5, 'mm'),
                show.legend = FALSE) +
  scale_edge_width(range = c(1,1)) +
  scale_edge_colour_gradient(low = "grey", high = "black") +
  geom_node_point(size = 5, aes(color = as.factor(name))) +
  scale_color_manual(name = "Party name",
                     values = c("AfD" = 'blue','Greens' = 'darkgreen', "FDP" = "yellow",
                                "Left" = "darkred", "SPD" = "red", "CDU/CSU" = "black")) +
  scale_edge_alpha_identity() +
  facet_edges(~type) +
  theme_bw() +
  theme(axis.title = element_blank(), 
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        legend.position = "bottom",
        panel.grid = element_blank())

```

\newpage

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.align="center", out.width="100%", fig.cap = "Directed issue engagement network graph for Swiss parties in press releases and tweets (four-day period) between January 2019 and September 2021."}

## create data frame
df <- filter(main_data,
             issue_engagement_tplus3 > 0 & country == "CH") %>%
  mutate(party_dyad = gsub("Mitte", "CVP/Mitte", party_dyad)) %>%
  mutate(party_dyad = gsub("CVP/PDC", "CVP/Mitte", party_dyad)) %>%
  group_by(party_dyad, type) %>%
  summarise_at(c("issue_engagement_tplus3"), sum, na.rm = TRUE)

df$party_a <- str_extract(df$party_dyad,
                          "[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- str_extract(df$party_dyad,
                          "-[[:alnum:]]{1,}\\/?[[:alpha:]]{0,}[[:space:]]?[[:alpha:]]{0,}")
df$party_b <- gsub("\\-", "", df$party_b)
df <- df[, c("party_a", "party_b", "type", "issue_engagement_tplus3")]

## adjust party names
df$party_a <- gsub("BDP/PBD", "BDP", df$party_a)
df$party_a <- gsub("FDP/PLR", "FDP", df$party_a)
df$party_a <- gsub("GPS/PES", "GPS", df$party_a)
df$party_a <- gsub("SPS/PSS", "SPS", df$party_a)
df$party_a <- gsub("SVP/UDC", "SVP", df$party_a)
df$party_b <- gsub("BDP/PBD", "BDP", df$party_b)
df$party_b <- gsub("FDP/PLR", "FDP", df$party_b)
df$party_b <- gsub("GPS/PES", "GPS", df$party_b)
df$party_b <- gsub("SPS/PSS", "SPS", df$party_b)
df$party_b <- gsub("SVP/UDC", "SVP", df$party_b)

## graph object
graph <- as_tbl_graph(df, directed = TRUE)
edge_weight <- df$issue_engagement_tplus3 / 10000

graph <- graph %>%
  tidygraph::activate(edges) %>%
  mutate(edge_weights = edge_weight)

## plot
set.seed(1)
ggraph(graph, layout = "fr", weights = edge_weights) +
  geom_edge_arc(aes(alpha = 1,
                    width = edge_weight, 
                    color = edge_weights
                    ),
                strength = 0.5,
                arrow = arrow(angle = 30, length = unit(0.25, "inches"),
                              ends = "last", type = "closed"),
                check_overlap = TRUE,
                start_cap = circle(2.5, 'mm'),
                end_cap = circle(2.5, 'mm'),
                show.legend = FALSE) +
  scale_edge_width(range = c(1,1)) +
  scale_edge_colour_gradient(low = "grey", high = "black") +
  geom_node_point(size = 5, aes(color = as.factor(name))) +
  scale_color_manual(name = "Party name",
                     values = c("BDP" = 'orange', "CVP/Mitte" = "darkorange",
                                "FDP" = "yellow",
                                'GPS' = 'darkgreen', "GLP" = "green",
                                "SPS" = "red", "SVP" = "black")) +
  scale_edge_alpha_identity() +
  facet_edges(~type) +
  theme_bw() +
  theme(axis.title = element_blank(), 
        axis.text = element_blank(),
        axis.ticks = element_blank(),
        legend.position = "bottom",
        panel.grid = element_blank())

```

\newpage

## A.8 Regression models for press releases and tweets separately

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# filter data
data_sub <- filter(main_data, attention_source > 0)

# Press releases
data_pr <- filter(data_sub, type == "Press release")

m5 <- miceadds::glm.cluster(
  data = data_pr, 
  formula = issue_engagement_tplus0 ~ # dependent variable
    rile_difference + 
    party_perseat + 
    party_government + 
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m5_summary <- data.frame(summary(m5))[1:6, 1:4]
colnames(m5_summary) <- c("est", "sd", "z", "p")

# Tweets
data_tw <- filter(data_sub, type == "Tweet")

m6 <- miceadds::glm.cluster(
  data = data_tw, 
  formula = issue_engagement_tplus0 ~ # dependent variable
    rile_difference + 
    party_perseat + 
    party_government + 
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m6_summary <- data.frame(summary(m6))[1:6, 1:4]
colnames(m6_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus0 ~ # dependent variable
                rile_difference + 
                party_perseat +
                party_government + 
                election_campaign +
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models (one-day period) with moderating factors on issue engagement between parties for press releases and tweets separately.",
          column.labels = c("Press releases", "Tweets"),
          dep.var.labels = "Issue engagement",
          coef = list(m5_summary$est, 
                      m6_summary$est),
          se = list(m5_summary$sd,
                    m6_summary$sd),
          p = list(m5_summary$p,
                   m6_summary$p),
          covariate.labels = c("RILE difference",
                               "Party size",
                               "Party in government",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "Yes"),
                           c("Issue FEs", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m5$glm_res), digits = 1)),
                             printT(round(logLik(m6$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m5$glm_res$aic, digits = 1)),
                             printT(round(m6$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m5$glm_res$data)),
                             printT(nrow(m6$glm_res$data)))),
        notes = "Standard errors clustered by party dyad-issue.")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# filter data
data_sub <- filter(main_data, attention_source > 0)

# Press releases
data_pr <- filter(data_sub, type == "Press release")

m7 <- miceadds::glm.cluster(
  data = data_pr, 
  formula = issue_engagement_tplus1 ~ # dependent variable
    rile_difference + 
    party_perseat + 
    party_government + 
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m7_summary <- data.frame(summary(m7))[1:6, 1:4]
colnames(m7_summary) <- c("est", "sd", "z", "p")

# Tweets
data_tw <- filter(data_sub, type == "Tweet")

m8 <- miceadds::glm.cluster(
  data = data_tw, 
  formula = issue_engagement_tplus1 ~ # dependent variable
    rile_difference + 
    party_perseat + 
    party_government + 
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m8_summary <- data.frame(summary(m8))[1:6, 1:4]
colnames(m8_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus1 ~ # dependent variable
                rile_difference + 
                party_perseat +
                party_government + 
                election_campaign +
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models (two-day period) with moderating factors on issue engagement between parties for press releases and tweets separately.",
          column.labels = c("Press releases", "Tweets"),
          dep.var.labels = "Issue engagement",
          coef = list(m7_summary$est, 
                      m8_summary$est),
          se = list(m7_summary$sd,
                    m8_summary$sd),
          p = list(m7_summary$p,
                   m8_summary$p),
          covariate.labels = c("RILE difference",
                               "Party size",
                               "Party in government",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "Yes"),
                           c("Issue FEs", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m7$glm_res), digits = 1)),
                             printT(round(logLik(m8$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m7$glm_res$aic, digits = 1)),
                             printT(round(m8$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m7$glm_res$data)),
                             printT(nrow(m8$glm_res$data)))),
        notes = "Standard errors clustered by party dyad-issue.")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# filter data
data_sub <- filter(main_data, attention_source > 0)

# Press releases
data_pr <- filter(data_sub, type == "Press release")

m9 <- miceadds::glm.cluster(
  data = data_pr, 
  formula = issue_engagement_tplus2 ~ # dependent variable
    rile_difference + 
    party_perseat + 
    party_government + 
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m9_summary <- data.frame(summary(m9))[1:6, 1:4]
colnames(m9_summary) <- c("est", "sd", "z", "p")

# Tweets
data_tw <- filter(data_sub, type == "Tweet")

m10 <- miceadds::glm.cluster(
  data = data_tw, 
  formula = issue_engagement_tplus2 ~ # dependent variable
    rile_difference + 
    party_perseat + 
    party_government + 
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m10_summary <- data.frame(summary(m10))[1:6, 1:4]
colnames(m10_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus2 ~ # dependent variable
                rile_difference + 
                party_perseat +
                party_government + 
                election_campaign +
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models (three-day period) with moderating factors on issue engagement between parties for press releases and tweets separately.",
          column.labels = c("Press releases", "Tweets"),
          dep.var.labels = "Issue engagement",
          coef = list(m9_summary$est, 
                      m10_summary$est),
          se = list(m9_summary$sd,
                    m10_summary$sd),
          p = list(m9_summary$p,
                   m10_summary$p),
          covariate.labels = c("RILE difference",
                               "Party size",
                               "Party in government",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "Yes"),
                           c("Issue FEs", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m9$glm_res), digits = 1)),
                             printT(round(logLik(m10$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m9$glm_res$aic, digits = 1)),
                             printT(round(m10$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m9$glm_res$data)),
                             printT(nrow(m10$glm_res$data)))),
        notes = "Standard errors clustered by party dyad-issue.")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# filter data
data_sub <- filter(main_data, attention_source > 0)

# Press releases
data_pr <- filter(data_sub, type == "Press release")

m11 <- miceadds::glm.cluster(
  data = data_pr, 
  formula = issue_engagement_tplus3 ~ # dependent variable
    rile_difference + 
    party_perseat + 
    party_government + 
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m11_summary <- data.frame(summary(m11))[1:6, 1:4]
colnames(m11_summary) <- c("est", "sd", "z", "p")

# Tweets
data_tw <- filter(data_sub, type == "Tweet")

m12 <- miceadds::glm.cluster(
  data = data_tw, 
  formula = issue_engagement_tplus3 ~ # dependent variable
    rile_difference + 
    party_perseat + 
    party_government + 
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m12_summary <- data.frame(summary(m12))[1:6, 1:4]
colnames(m12_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus3 ~ # dependent variable
                rile_difference + 
                party_perseat +
                party_government + 
                election_campaign +
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models (four-day period) with moderating factors on issue engagement between parties for press releases and tweets separately.",
          column.labels = c("Press releases", "Tweets"),
          dep.var.labels = "Issue engagement",
          coef = list(m11_summary$est, 
                      m12_summary$est),
          se = list(m11_summary$sd,
                    m12_summary$sd),
          p = list(m11_summary$p,
                   m12_summary$p),
          covariate.labels = c("RILE difference",
                               "Party size",
                               "Party in government",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "Yes"),
                           c("Issue FEs", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m11$glm_res), digits = 1)),
                             printT(round(logLik(m12$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m11$glm_res$aic, digits = 1)),
                             printT(round(m12$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m11$glm_res$data)),
                             printT(nrow(m12$glm_res$data)))),
        notes = "Standard errors clustered by party dyad-issue.")

```

\newpage

## A.9 Regression models per country

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# filter data
data_sub <- filter(main_data, attention_source > 0)

# All
m13 <- miceadds::glm.cluster(
  data = data_sub,
  formula = issue_engagement_tplus0 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m13_summary <- data.frame(summary(m13))[c(1:5, 46:48, 6:7), 1:4]
colnames(m13_summary) <- c("est", "sd", "z", "p")

# Austria
data_at <- filter(data_sub, country == "AT")

m14 <- miceadds::glm.cluster(
  data = data_at, 
  formula = issue_engagement_tplus0 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type + 
    party_government*type + 
    election_campaign + #control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m14_summary <- data.frame(summary(m14))[c(1:5, 43:45, 6), 1:4]
colnames(m14_summary) <- c("est", "sd", "z", "p")

# Germany
data_de <- filter(data_sub, country == "DE")

m15 <- miceadds::glm.cluster(
  data = data_de, 
  formula = issue_engagement_tplus0 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m15_summary <- data.frame(summary(m15))[c(1:5, 43:45, 6), 1:4]
colnames(m15_summary) <- c("est", "sd", "z", "p")

# Switzerland
data_ch <- filter(data_sub, country == "CH")

m16 <- miceadds::glm.cluster(
  data = data_ch, 
  formula = issue_engagement_tplus0 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type + 
    party_government*type + 
    election_campaign + # control
    referendum_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m16_summary <- data.frame(summary(m16))[c(1:5, 44:46, 6:7), 1:4]
colnames(m16_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus0 ~ # dependent variable
                type + 
                rile_difference*type + 
                party_perseat*type +
                party_government*type + 
                election_campaign +
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm, fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models (one-day period) with moderating factors on issue engagement between parties per country.",
          column.labels = c("All", "AT", "DE", "CH"),
          dep.var.labels = "Issue engagement",
          coef = list(m13_summary$est, m14_summary$est, 
                      m15_summary$est, m16_summary$est),
          se = list(m13_summary$sd, m14_summary$sd,
                    m15_summary$sd, m16_summary$sd),
          p = list(m13_summary$p, m14_summary$p,
                   m15_summary$p, m16_summary$p),
          covariate.labels = c("Tweet",
                               "RILE difference",
                               "Party size",
                               "Party in government",
                               "RILE difference:Tweet", 
                               "Party size:Tweet",
                               "Party in government:Tweet",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "No", "No", "No"),
                           c("Issue FEs", "Yes", "Yes", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m13$glm_res), digits = 1)),
                             printT(round(logLik(m14$glm_res), digits = 1)),
                             printT(round(logLik(m15$glm_res), digits = 1)),
                             printT(round(logLik(m16$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m13$glm_res$aic, digits = 1)),
                             printT(round(m14$glm_res$aic, digits = 1)),
                             printT(round(m15$glm_res$aic, digits = 1)),
                             printT(round(m16$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m13$glm_res$data)),
                             printT(nrow(m14$glm_res$data)),
                             printT(nrow(m15$glm_res$data)),
                             printT(nrow(m16$glm_res$data)))),
        notes = "Standard errors clustered by party dyad-issue.")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# All
m17 <- miceadds::glm.cluster(
  data = data_sub,
  formula = issue_engagement_tplus1 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m17_summary <- data.frame(summary(m17))[c(1:5, 46:48, 6:7), 1:4]
colnames(m17_summary) <- c("est", "sd", "z", "p")

# Austria
data_at <- filter(data_sub, country == "AT")

m18 <- miceadds::glm.cluster(
  data = data_at, 
  formula = issue_engagement_tplus1 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m18_summary <- data.frame(summary(m18))[c(1:5, 43:45, 6), 1:4]
colnames(m18_summary) <- c("est", "sd", "z", "p")

# Germany
data_de <- filter(data_sub, country == "DE")

m19 <- miceadds::glm.cluster(
  data = data_de, 
  formula = issue_engagement_tplus1 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type + 
    party_government*type + 
    election_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m19_summary <- data.frame(summary(m19))[c(1:5, 43:45, 6), 1:4]
colnames(m19_summary) <- c("est", "sd", "z", "p")

# Switzerland
data_ch <- filter(data_sub, country == "CH")

m20 <- miceadds::glm.cluster(
  data = data_ch, 
  formula = issue_engagement_tplus1 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type + 
    election_campaign + # control
    referendum_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m20_summary <- data.frame(summary(m20))[c(1:5, 44:46, 6:7), 1:4]
colnames(m20_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus1 ~ # dependent variable
                type + 
                rile_difference*type + 
                party_perseat*type + 
                party_government*type + 
                election_campaign +
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm, fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models (two-day period) with moderating factors on issue engagement between parties per country.",
          column.labels = c("All", "AT", "DE", "CH"),
          dep.var.labels = "Issue engagement",
          coef = list(m17_summary$est, m18_summary$est, 
                      m19_summary$est, m20_summary$est),
          se = list(m17_summary$sd, m18_summary$sd,
                    m19_summary$sd, m20_summary$sd),
          p = list(m17_summary$p, m18_summary$p,
                   m19_summary$p, m20_summary$p),
          covariate.labels = c("Tweet",
                               "RILE difference",
                               "Party size",
                               "Party in government",
                               "RILE difference:Tweet", 
                               "Party size:Tweet",
                               "Party in government:Tweet",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "No", "No", "No"),
                           c("Issue FEs", "Yes", "Yes", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m17$glm_res), digits = 1)),
                             printT(round(logLik(m18$glm_res), digits = 1)),
                             printT(round(logLik(m19$glm_res), digits = 1)),
                             printT(round(logLik(m20$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m17$glm_res$aic, digits = 1)),
                             printT(round(m18$glm_res$aic, digits = 1)),
                             printT(round(m19$glm_res$aic, digits = 1)),
                             printT(round(m20$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m17$glm_res$data)),
                             printT(nrow(m18$glm_res$data)),
                             printT(nrow(m19$glm_res$data)),
                             printT(nrow(m20$glm_res$data)))),
        notes = "Standard errors clustered by party dyad-issue.")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# All
m21 <- miceadds::glm.cluster(
  data = data_sub,
  formula = issue_engagement_tplus2 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m21_summary <- data.frame(summary(m21))[c(1:5, 46:48, 6:7), 1:4]
colnames(m21_summary) <- c("est", "sd", "z", "p")

# Austria
data_at <- filter(data_sub, country == "AT")

m22 <- miceadds::glm.cluster(
  data = data_at, 
  formula = issue_engagement_tplus2 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m22_summary <- data.frame(summary(m22))[c(1:5, 43:45, 6), 1:4]
colnames(m22_summary) <- c("est", "sd", "z", "p")

# Germany
data_de <- filter(data_sub, country == "DE")

m23 <- miceadds::glm.cluster(
  data = data_de, 
  formula = issue_engagement_tplus2 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type + 
    party_government*type +
    election_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m23_summary <- data.frame(summary(m23))[c(1:5, 43:45, 6), 1:4]
colnames(m23_summary) <- c("est", "sd", "z", "p")

# Switzerland
data_ch <- filter(data_sub, country == "CH")

m24 <- miceadds::glm.cluster(
  data = data_ch, 
  formula = issue_engagement_tplus2 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m24_summary <- data.frame(summary(m24))[c(1:5, 44:46, 6:7), 1:4]
colnames(m24_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus2 ~ # dependent variable
                type + 
                rile_difference*type + 
                party_perseat*type +
                party_government*type + 
                election_campaign +
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm, fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models (three-day period) with moderating factors on issue engagement between parties per country.",
          column.labels = c("All", "AT", "DE", "CH"),
          dep.var.labels = "Issue engagement",
          coef = list(m21_summary$est, m22_summary$est, 
                      m23_summary$est, m24_summary$est),
          se = list(m21_summary$sd, m22_summary$sd,
                    m23_summary$sd, m24_summary$sd),
          p = list(m21_summary$p, m22_summary$p,
                   m23_summary$p, m24_summary$p),
          covariate.labels = c("Tweet",
                               "RILE difference",
                               "Party size",
                               "Party in government",
                               "RILE difference:Tweet", 
                               "Party size:Tweet",
                               "Party in government:Tweet",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "No", "No", "No"),
                           c("Issue FEs", "Yes", "Yes", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m21$glm_res), digits = 1)),
                             printT(round(logLik(m22$glm_res), digits = 1)),
                             printT(round(logLik(m23$glm_res), digits = 1)),
                             printT(round(logLik(m24$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m21$glm_res$aic, digits = 1)),
                             printT(round(m22$glm_res$aic, digits = 1)),
                             printT(round(m23$glm_res$aic, digits = 1)),
                             printT(round(m24$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m21$glm_res$data)),
                             printT(nrow(m22$glm_res$data)),
                             printT(nrow(m23$glm_res$data)),
                             printT(nrow(m24$glm_res$data)))),
        notes = "Standard errors clustered by party dyad-issue.")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# All
m25 <- miceadds::glm.cluster(
  data = data_sub,
  formula = issue_engagement_tplus3 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type + 
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m25_summary <- data.frame(summary(m25))[c(1:5, 46:48, 6:7), 1:4]
colnames(m25_summary) <- c("est", "sd", "z", "p")

# Austria
data_at <- filter(data_sub, country == "AT")

m26 <- miceadds::glm.cluster(
  data = data_at, 
  formula = issue_engagement_tplus3 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type + 
    party_government*type +
    election_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m26_summary <- data.frame(summary(m26))[c(1:5, 43:45, 6), 1:4]
colnames(m26_summary) <- c("est", "sd", "z", "p")

# Germany
data_de <- filter(data_sub, country == "DE")

m27 <- miceadds::glm.cluster(
  data = data_de, 
  formula = issue_engagement_tplus3 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type + 
    election_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m27_summary <- data.frame(summary(m27))[c(1:5, 43:45, 6), 1:4]
colnames(m27_summary) <- c("est", "sd", "z", "p")

# Switzerland
data_ch <- filter(data_sub, country == "CH")

m28 <- miceadds::glm.cluster(
  data = data_ch, 
  formula = issue_engagement_tplus3 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type + 
    election_campaign + # control
    referendum_campaign + # control
    topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m28_summary <- data.frame(summary(m28))[c(1:5, 44:46, 6:7), 1:4]
colnames(m28_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus3 ~ # dependent variable
                type + 
                rile_difference*type + 
                party_perseat*type + 
                party_government*type + 
                election_campaign +
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm, fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models (four-day period) with moderating factors on issue engagement between parties per country.",
          column.labels = c("All", "AT", "DE", "CH"),
          dep.var.labels = "Issue engagement",
          coef = list(m25_summary$est, m26_summary$est, 
                      m27_summary$est, m28_summary$est),
          se = list(m25_summary$sd, m26_summary$sd,
                    m27_summary$sd, m28_summary$sd),
          p = list(m25_summary$p, m26_summary$p,
                   m27_summary$p, m28_summary$p),
          covariate.labels = c("Tweet",
                               "RILE difference",
                               "Party size",
                               "Party in government",
                               "RILE difference:Tweet", 
                               "Party size:Tweet",
                               "Party in government:Tweet",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "No", "No", "No"),
                           c("Issue FEs", "Yes", "Yes", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m25$glm_res), digits = 1)),
                             printT(round(logLik(m26$glm_res), digits = 1)),
                             printT(round(logLik(m27$glm_res), digits = 1)),
                             printT(round(logLik(m28$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m25$glm_res$aic, digits = 1)),
                             printT(round(m26$glm_res$aic, digits = 1)),
                             printT(round(m27$glm_res$aic, digits = 1)),
                             printT(round(m28$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m25$glm_res$data)),
                             printT(nrow(m26$glm_res$data)),
                             printT(nrow(m27$glm_res$data)),
                             printT(nrow(m28$glm_res$data)))),
        notes = "Standard errors clustered by party dyad-issue.")

```

\newpage

## A.10 Regression models controlling for issue-specific effects following jackknife logic

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# estimate regression models 
topic_list <- sort(unique(data_sub$topic_label))

df_summary <- c()
for(i in 1:length(topic_list)) {
  
  topic_tmp <- topic_list[i]
  
  data_tmp <- filter(data_sub, topic_label != topic_tmp)

  m_tmp <- miceadds::glm.cluster(
    data = data_tmp, 
    formula = issue_engagement_tplus3 ~ # dependent variable
      type + 
      rile_difference*type + 
      party_perseat*type +
      party_government*type +
      election_campaign + # control
      referendum_campaign + # control
      country + topic_label, # fixed effects
    cluster = "cluster", 
    family = "binomial")

    m_tmp_summary <- data.frame(summary(m_tmp))[, 1:4]
    m_tmp_summary$variable <- rownames(m_tmp_summary)
    m_tmp_summary$issue <- topic_tmp
    rownames(m_tmp_summary) <- NULL
    conf_int <- as.data.frame(confint(m_tmp, level = 0.9)) %>%
      rename("lower_bound" = "5 %", "upper_bound" = "95 %")
    m_tmp_summary <- cbind(m_tmp_summary, conf_int) %>%
      select(Estimate, Std..Error, z.value, Pr...z.., lower_bound, upper_bound,
             variable, issue)
    
    df_summary <- rbind(df_summary, m_tmp_summary)
}

# create table
df <- df_summary %>%
  select(Estimate, variable) %>%
  group_by(variable) %>%
  summarise(Min = min(Estimate), Median = median(Estimate), Mean = mean(Estimate), Max = max(Estimate), SD = sd(Estimate))
df <- df[c(1, 45, 8, 6, 5, 48, 47, 46, 4, 7), ]
df$variable <- c("Constant", 
                 "Tweet",
                 "RILE difference", 
                 "Party size",
                 "Party in government",
                 "RILE difference:Tweet", 
                 "Party size:Tweet", 
                 "Party in government:Tweet",
                 "Election campaign",
                 "Referendum campaign")
colnames(df)[1] <- "Variable" 

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# print table
df[, 2:6] <- round(df[, 2:6], digits = 3)

kable(df,
      format = "latex", booktabs = TRUE,
      caption = "Summary statistics of coefficients for regression models (four-day period) following jackknife logic.") %>%
  kable_styling(latex_options = "HOLD_position")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, out.width = "100%", fig.align = "center", results='asis', fig.cap = "Coefficients for the influence of tweets on issue engagement based on regression models (four-day period) following jackknife logic."}

# print plot
df_summary$variable <- factor(df_summary$variable,
                              levels = c("typeTweet",
                                         "rile_difference",
                                         "party_perseat",
                                         "party_government",
                                         "typeTweet:rile_difference",
                                         "typeTweet:party_perseat",
                                         "typeTweet:party_government"))

df_summary %>%
  filter(variable == "typeTweet" |
           variable == "rile_difference" |
           variable == "party_perseat" |
           variable == "party_government" |
           variable == "typeTweet:rile_difference" |
           variable == "typeTweet:perseat" |
           variable == "typeTweet:party_government") %>%
  ggplot(aes(x = Estimate, y = issue)) +
  geom_point() +
  geom_errorbar(aes(xmin = lower_bound, xmax = upper_bound)) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  xlab("Coefficient") +
  ylab("Issue removed from regression") +
  theme_bw() + 
  facet_wrap_paginate(~ variable,
                      scales = "free_x",
                      ncol = 1,
                      nrow = 1,
                      labeller = as_labeller(c("typeTweet"="Tweet")),
                      page = 1)

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, out.width = "100%", fig.align = "center", results='asis', fig.cap = "Coefficients for the influence of ideological distance on issue engagement in press releases based on regression models (four-day period) following jackknife logic."}

# print plot
df_summary %>%
  filter(variable == "typeTweet" |
           variable == "rile_difference" |
           variable == "party_perseat" |
           variable == "party_government" |
           variable == "typeTweet:rile_difference" |
           variable == "typeTweet:perseat" |
           variable == "typeTweet:party_government") %>%
  ggplot(aes(x = Estimate, y = issue)) +
  geom_point() +
  geom_errorbar(aes(xmin = lower_bound, xmax = upper_bound)) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  xlab("Coefficient") +
  ylab("Issue removed from regression") +
  theme_bw() + 
  facet_wrap_paginate(~ variable,
                      scales = "free_x",
                      ncol = 1,
                      nrow = 1,
                      labeller = as_labeller(c("rile_difference"="RILE difference")),
                      page = 2)

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, out.width = "100%", fig.align = "center", results='asis', fig.cap = "Coefficients for the influence of party size on issue engagement in press releases based on regression models (four-day period) following jackknife logic."}

# print plot
df_summary %>%
  filter(variable == "typeTweet" |
           variable == "rile_difference" |
           variable == "party_perseat" |
           variable == "party_government" |
           variable == "typeTweet:rile_difference" |
           variable == "typeTweet:perseat" |
           variable == "typeTweet:party_government") %>%
  ggplot(aes(x = Estimate, y = issue)) +
  geom_point() +
  geom_errorbar(aes(xmin = lower_bound, xmax = upper_bound)) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  xlab("Coefficient") +
  ylab("Issue removed from regression") +
  theme_bw() + 
  facet_wrap_paginate(~ variable,
                      scales = "free_x",
                      ncol = 1,
                      nrow = 1,
                      labeller = as_labeller(c("party_perseat"="Party size")),
                      page = 3)

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, out.width = "100%", fig.align = "center", results='asis', fig.cap = "Coefficients for the influence of government participation on issue engagement in press releases based on regression models (four-day period) following jackknife logic."}

# print plot
df_summary %>%
  filter(variable == "typeTweet" |
           variable == "rile_difference" |
           variable == "party_perseat" |
           variable == "party_government" |
           variable == "typeTweet:rile_difference" |
           variable == "typeTweet:perseat" |
           variable == "typeTweet:party_government") %>%
  ggplot(aes(x = Estimate, y = issue)) +
  geom_point() +
  geom_errorbar(aes(xmin = lower_bound, xmax = upper_bound)) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  xlab("Coefficient") +
  ylab("Issue removed from regression") +
  theme_bw() + 
  facet_wrap_paginate(~ variable,
                      scales = "free_x",
                      ncol = 1,
                      nrow = 1,
                      labeller = as_labeller(c("party_government"="Party in government")),
                      page = 4)

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, out.width = "100%", fig.align = "center", results='asis', fig.cap = "Coefficients for the interaction effect between ideological distance and tweets on issue engagement based on regression models (four-day period) following jackknife logic."}

# print plot
df_summary %>%
  filter(variable == "typeTweet" |
           variable == "rile_difference" |
           variable == "party_perseat" |
           variable == "party_government" |
           variable == "typeTweet:rile_difference" |
           variable == "typeTweet:perseat" |
           variable == "typeTweet:party_government") %>%
  ggplot(aes(x = Estimate, y = issue)) +
  geom_point() +
  geom_errorbar(aes(xmin = lower_bound, xmax = upper_bound)) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  xlab("Coefficient") +
  ylab("Issue removed from regression") +
  theme_bw() + 
  facet_wrap_paginate(~ variable,
                      scales = "free_x",
                      ncol = 1,
                      nrow = 1,
                      labeller = as_labeller(c("typeTweet:rile_difference"="RILE difference:Tweet")),
                      page = 5)

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, out.width = "100%", fig.align = "center", results='asis', fig.cap = "Coefficients for the interaction effect between party size and tweets on issue engagement based on regression models (four-day period) following jackknife logic."}

# print plot
df_summary %>%
  filter(variable == "typeTweet" |
           variable == "rile_difference" |
           variable == "party_perseat" |
           variable == "party_government" |
           variable == "typeTweet:rile_difference" |
           variable == "typeTweet:party_perseat" |
           variable == "typeTweet:party_government") %>%
  ggplot(aes(x = Estimate, y = issue)) +
  geom_point() +
  geom_errorbar(aes(xmin = lower_bound, xmax = upper_bound)) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  xlab("Coefficient") +
  ylab("Issue removed from regression") +
  theme_bw() + 
  facet_wrap_paginate(~ variable,
                      scales = "free_x",
                      ncol = 1,
                      nrow = 1,
                      labeller = as_labeller(c("typeTweet:party_perseat"="Party size:Tweet")),
                      page = 6)

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, out.width = "100%", fig.align = "center", results='asis', fig.cap = "Coefficients for the interaction effect between government participation and tweets on issue engagement based on regression models (four-day period) following jackknife logic."}

# print plot
df_summary %>%
  filter(variable == "typeTweet" |
           variable == "rile_difference" |
           variable == "party_perseat" |
           variable == "party_government" |
           variable == "typeTweet:rile_difference" |
           variable == "typeTweet:perseat" |
           variable == "typeTweet:party_government") %>%
  ggplot(aes(x = Estimate, y = issue)) +
  geom_point() +
  geom_errorbar(aes(xmin = lower_bound, xmax = upper_bound)) +
  geom_vline(xintercept = 0, linetype = "dashed") +
  xlab("Coefficient") +
  ylab("Issue removed from regression") +
  theme_bw() + 
  facet_wrap_paginate(~ variable,
                      scales = "free_x",
                      ncol = 1,
                      nrow = 1,
                      labeller = as_labeller(c("typeTweet:party_government"="Party in government:Tweet")),
                      page = 6)

```

\newpage

## A.11 Regression models for Covid-19-related and non-Covid-19-related issues

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="hide"}

# All
m29 <- miceadds::glm.cluster(
  data = data_sub,
  formula = issue_engagement_tplus3 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type + 
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m29_summary <- data.frame(summary(m29))[c(1:5, 46:48, 6:7), 1:4]
colnames(m29_summary) <- c("est", "sd", "z", "p")

# No Covid-related topics
data_no_covid <- filter(data_sub,
                        topic_label != "Covid-19 (measures)") %>%
  filter(topic_label != "Covid-19 (support)") %>%
  filter(topic_label != "Covid-19 (vaccination)")

m30 <- miceadds::glm.cluster(
  data = data_no_covid, 
  formula = issue_engagement_tplus3 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type + 
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m30_summary <- data.frame(summary(m30))[c(1:5, 43:45, 6:7), 1:4]
colnames(m30_summary) <- c("est", "sd", "z", "p")

# Covid-related topics
data_covid <- filter(data_sub,
                     topic_label == "Covid-19 (measures)" |
                       topic_label == "Covid-19 (support)" |
                       topic_label == "Covid-19 (vaccination)")

m31 <- miceadds::glm.cluster(
  data = data_covid, 
  formula = issue_engagement_tplus3 ~ # dependent variable
    type + 
    rile_difference*type + 
    party_perseat*type +
    party_government*type +
    election_campaign + # control
    referendum_campaign + # control
    country + topic_label, # fixed effects
  cluster = "cluster", 
  family = "binomial")

m31_summary <- data.frame(summary(m31))[c(1:5, 12:14, 6:7), 1:4]
colnames(m31_summary) <- c("est", "sd", "z", "p")

```

```{r, warning=FALSE, message=FALSE, echo=FALSE, fig.pos = "H", results="asis"}

# initialise table
fake_lm <- lm(issue_engagement_tplus3 ~ # dependent variable
                type + 
                rile_difference*type + 
                party_perseat*type +
                party_government*type +
                election_campaign + 
                referendum_campaign,
              data_sub)

# print table
stargazer(list(fake_lm, fake_lm, fake_lm),
          header = FALSE,
          title = "Regression models (four-day period) with for moderating factors on issue engagement across all issues, non-Covid-19-related issues and Covid-19-related issues.",
          column.labels = c("All issues", "Non-Covid-19-related", "Covid-19-related"),
          dep.var.labels = "Issue engagement",
          coef = list(m29_summary$est,
                      m30_summary$est, 
                      m31_summary$est),
          se = list(m29_summary$sd,
                    m30_summary$sd,
                    m31_summary$sd),
          p = list(m29_summary$p, 
                   m30_summary$p,
                   m31_summary$p),
          covariate.labels = c("Tweet",
                               "RILE difference",
                               "Party size",
                               "Party in government",
                               "RILE difference:Tweet", 
                               "Party size:Tweet",
                               "Party in government:Tweet",
                               "Election campaign",
                               "Referendum campaign",
                               "Constant"),
          type = "latex", 
          omit.stat = "all",
          add.lines = list(c("Country FEs", "Yes", "Yes", "Yes", "Yes"),
                           c("Issue FEs", "Yes", "Yes", "Yes", "Yes"),
                           c("Log-likelihood",
                             printT(round(logLik(m29$glm_res), digits = 1)),
                             printT(round(logLik(m30$glm_res), digits = 1)),
                             printT(round(logLik(m31$glm_res), digits = 1))),
                           c("AIC",
                             printT(round(m29$glm_res$aic, digits = 1)),
                             printT(round(m30$glm_res$aic, digits = 1)),
                             printT(round(m31$glm_res$aic, digits = 1))),
                           c("Observations", 
                             printT(nrow(m29$glm_res$data)),
                             printT(nrow(m30$glm_res$data)),
                             printT(nrow(m31$glm_res$data)))),
        notes = "Standard errors clustered by party dyad-issue.")

```

